"""
综合实战项目：用户管理系统

整合第一阶段所有知识点：
- 第1章：路由与参数
- 第2章：请求体与数据验证
- 第3章：响应模型与状态码
- 第4章：依赖注入系统

运行方式：
cd /Users/baimu/PycharmProjects/fastApiProject3
uvicorn stage1_basics.final_project.main:app --reload --port 8006

访问：
- Swagger UI: http://127.0.0.1:8006/docs
- ReDoc: http://127.0.0.1:8006/redoc
"""

from fastapi import FastAPI, HTTPException, status, Depends, Path, Query
from typing import List, Dict, Any

from .models import (
    UserRegister,
    UserLogin,
    UserUpdate,
    UserResponse,
    LoginResponse,
    RoleUpdate,
    SystemStats,
)
from .dependencies import (
    get_db,
    get_current_user,
    require_admin,
    check_user_permission,
    PaginationParams,
    UserFilterParams,
)
from . import database
from .utils import verify_password, create_access_token


# ========== 应用初始化 ==========

app = FastAPI(
    title="🎯 用户管理系统",
    description="""
    ## 综合实战项目
    
    整合了 FastAPI 第一阶段的所有知识点：
    - ✅ 路由与参数（GET/POST/PATCH/DELETE）
    - ✅ 请求体与数据验证（Pydantic 模型）
    - ✅ 响应模型与状态码
    - ✅ 依赖注入系统（认证、权限、分页）
    
    ## 功能模块
    - 🔐 用户认证：注册、登录、Token 认证
    - 👤 用户管理：CRUD 操作、搜索、分页
    - 🔒 权限控制：普通用户 / 管理员
    - 📊 系统统计：用户数据统计
    
    ## 测试账号
    | 用户名 | 密码 | 角色 |
    |--------|------|------|
    | admin | Admin123 | 管理员 |
    | john | User123 | 普通用户 |
    | jane | User123 | 普通用户 |
    """,
    version="1.0.0",
    contact={
        "name": "FastAPI 学习项目",
        "url": "https://fastapi.tiangolo.com",
    },
    license_info={
        "name": "MIT License",
    },
)


# ========== 根路径 ==========


@app.get("/", tags=["系统"])
async def root():
    """系统根路径"""
    return {
        "message": "欢迎使用用户管理系统！",
        "version": "1.0.0",
        "docs": "/docs",
        "features": [
            "用户注册和登录",
            "Token 认证",
            "角色权限控制",
            "用户 CRUD 操作",
            "搜索和分页",
        ],
    }


@app.get("/health", tags=["系统"])
async def health_check():
    """健康检查"""
    return {
        "status": "healthy",
        "database": "connected",
        "timestamp": database.get_current_timestamp().isoformat(),
    }


# ========== 认证相关 ==========


@app.post(
    "/api/auth/register",
    response_model=UserResponse,
    status_code=status.HTTP_201_CREATED,
    tags=["认证"],
    summary="用户注册",
)
async def register(
    user_data: UserRegister,
    db = Depends(get_db),
):
    """
    用户注册
    
    ## 验证规则
    - 用户名：3-20 字符，只能包含字母、数字和下划线
    - 邮箱：有效的邮箱格式
    - 密码：至少 8 字符，必须包含大写、小写和数字
    - 年龄：0-150
    
    ## 返回
    - 201：注册成功，返回用户信息
    - 409：用户名或邮箱已存在
    """
    # 检查用户名是否已存在
    if db.get_user_by_username(user_data.username):
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"用户名 '{user_data.username}' 已被使用",
        )
    
    # 检查邮箱是否已存在
    if db.get_user_by_email(user_data.email):
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"邮箱 '{user_data.email}' 已被使用",
        )
    
    # 创建用户
    new_user = db.create_user(user_data)
    
    return new_user


@app.post(
    "/api/auth/login",
    response_model=LoginResponse,
    tags=["认证"],
    summary="用户登录",
)
async def login(
    login_data: UserLogin,
    db = Depends(get_db),
):
    """
    用户登录
    
    ## 验证流程
    1. 验证用户名是否存在
    2. 验证密码是否正确
    3. 检查用户状态
    4. 生成访问令牌
    
    ## 返回
    - 200：登录成功，返回 token 和用户信息
    - 401：用户名或密码错误
    - 403：用户已被停用
    """
    # 查询用户
    user = db.get_user_by_username(login_data.username)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或密码错误",
        )
    
    # 验证密码
    if not verify_password(login_data.password, user.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或密码错误",
        )
    
    # 检查用户状态
    if not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="用户已被停用",
        )
    
    # 生成 token
    access_token = create_access_token(user.username)
    
    return LoginResponse(
        access_token=access_token,
        token_type="bearer",
        user=user,
    )


@app.get(
    "/api/auth/me",
    response_model=UserResponse,
    tags=["认证"],
    summary="获取当前用户信息",
)
async def get_current_user_info(
    current_user=Depends(get_current_user),
):
    """
    获取当前登录用户的信息
    
    需要认证：✅
    
    ## Headers
    ```
    Authorization: Bearer <access_token>
    ```
    """
    return current_user


# ========== 用户管理 ==========


@app.get(
    "/api/users",
    tags=["用户管理"],
    summary="获取用户列表",
)
async def get_users(
    pagination: PaginationParams = Depends(),
    filters: UserFilterParams = Depends(),
    current_user=Depends(get_current_user),
    db = Depends(get_db),
) -> Dict[str, Any]:
    """
    获取用户列表（支持搜索、筛选、分页）
    
    需要认证：✅
    
    ## 查询参数
    - **page**: 页码（从 1 开始）
    - **page_size**: 每页数量（最多 100）
    - **search**: 搜索关键词（匹配用户名或邮箱）
    - **role**: 角色筛选（user/admin）
    - **is_active**: 活跃状态筛选
    
    ## 返回
    包含用户列表和分页信息
    """
    # 获取用户列表
    users = db.get_all_users(
        skip=pagination.skip,
        limit=pagination.limit,
        search=filters.search,
        role=filters.role,
        is_active=filters.is_active,
    )
    
    # 获取总数
    total = db.count_users(
        search=filters.search,
        role=filters.role,
        is_active=filters.is_active,
    )
    
    # 转换为 UserResponse 以隐藏敏感信息
    user_responses = [UserResponse.model_validate(user) for user in users]
    
    return {
        "users": user_responses,
        "pagination": pagination.get_pagination_info(total),
    }


@app.get(
    "/api/users/{user_id}",
    response_model=UserResponse,
    tags=["用户管理"],
    summary="获取指定用户",
)
async def get_user(
    user_id: int = Path(..., ge=1, description="用户 ID"),
    current_user=Depends(get_current_user),
    db = Depends(get_db),
):
    """
    获取指定用户的详细信息
    
    需要认证：✅
    
    ## 返回
    - 200：用户信息
    - 404：用户不存在
    """
    user = db.get_user_by_id(user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 ID {user_id} 不存在",
        )
    
    return user


@app.patch(
    "/api/users/{user_id}",
    response_model=UserResponse,
    tags=["用户管理"],
    summary="更新用户信息",
)
async def update_user(
    user_id: int = Path(..., ge=1, description="用户 ID"),
    user_data: UserUpdate = ...,
    current_user=Depends(get_current_user),
    db = Depends(get_db),
):
    """
    更新用户信息
    
    需要认证：✅
    权限要求：本人或管理员
    
    ## 可更新字段
    - email: 邮箱
    - full_name: 全名
    - age: 年龄
    
    ## 返回
    - 200：更新成功，返回更新后的用户信息
    - 403：权限不足
    - 404：用户不存在
    - 409：邮箱已被使用
    """
    # 检查权限
    if not check_user_permission(user_id, current_user):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="只能修改自己的信息",
        )
    
    # 检查用户是否存在
    user = db.get_user_by_id(user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 ID {user_id} 不存在",
        )
    
    # 如果要更新邮箱，检查邮箱是否已被使用
    if user_data.email:
        existing_user = db.get_user_by_email(user_data.email)
        if existing_user and existing_user.id != user_id:
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail=f"邮箱 '{user_data.email}' 已被使用",
            )
    
    # 更新用户
    updated_user = db.update_user(user_id, user_data)
    
    return updated_user


@app.delete(
    "/api/users/{user_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    tags=["用户管理"],
    summary="删除用户",
)
async def delete_user(
    user_id: int = Path(..., ge=1, description="用户 ID"),
    admin_user=Depends(require_admin),
    db = Depends(get_db),
):
    """
    删除用户（硬删除）
    
    需要认证：✅
    权限要求：管理员
    
    ## 返回
    - 204：删除成功（无内容）
    - 403：权限不足
    - 404：用户不存在
    """
    # 检查用户是否存在
    user = db.get_user_by_id(user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 ID {user_id} 不存在",
        )
    
    # 不允许删除自己
    if user_id == admin_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="不能删除自己的账号",
        )
    
    # 删除用户
    db.delete_user(user_id)


# ========== 管理员功能 ==========


@app.get(
    "/api/admin/stats",
    response_model=SystemStats,
    tags=["管理员"],
    summary="系统统计",
)
async def get_system_stats(
    admin_user=Depends(require_admin),
    db = Depends(get_db),
):
    """
    获取系统统计信息
    
    需要认证：✅
    权限要求：管理员
    
    ## 统计内容
    - 总用户数
    - 活跃用户数
    - 停用用户数
    - 管理员数
    - 普通用户数
    """
    stats = db.get_user_stats()
    return SystemStats(**stats)


@app.patch(
    "/api/admin/users/{user_id}/role",
    response_model=UserResponse,
    tags=["管理员"],
    summary="修改用户角色",
)
async def update_user_role(
    user_id: int = Path(..., ge=1, description="用户 ID"),
    role_data: RoleUpdate = ...,
    admin_user=Depends(require_admin),
    db = Depends(get_db),
):
    """
    修改用户角色
    
    需要认证：✅
    权限要求：管理员
    
    ## 角色
    - user: 普通用户
    - admin: 管理员
    
    ## 返回
    - 200：修改成功，返回更新后的用户信息
    - 403：权限不足
    - 404：用户不存在
    """
    # 检查用户是否存在
    user = db.get_user_by_id(user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 ID {user_id} 不存在",
        )
    
    # 不允许修改自己的角色
    if user_id == admin_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="不能修改自己的角色",
        )
    
    # 更新角色
    updated_user = db.update_user_role(user_id, role_data.role)
    
    return updated_user


@app.patch(
    "/api/admin/users/{user_id}/deactivate",
    response_model=UserResponse,
    tags=["管理员"],
    summary="停用用户",
)
async def deactivate_user(
    user_id: int = Path(..., ge=1, description="用户 ID"),
    admin_user=Depends(require_admin),
    db = Depends(get_db),
):
    """
    停用用户（软删除）
    
    需要认证：✅
    权限要求：管理员
    
    ## 返回
    - 200：停用成功，返回更新后的用户信息
    - 403：权限不足
    - 404：用户不存在
    """
    # 检查用户是否存在
    user = db.get_user_by_id(user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 ID {user_id} 不存在",
        )
    
    # 不允许停用自己
    if user_id == admin_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="不能停用自己的账号",
        )
    
    # 停用用户
    updated_user = db.deactivate_user(user_id)
    
    return updated_user


# ========== 启动事件 ==========


@app.on_event("startup")
async def startup_event():
    """应用启动时执行"""
    print("=" * 60)
    print("🚀 用户管理系统启动成功！")
    print("=" * 60)
    print("📚 API 文档: http://127.0.0.1:8006/docs")
    print("📖 ReDoc: http://127.0.0.1:8006/redoc")
    print("=" * 60)
    print("🔐 测试账号:")
    print("  管理员 - 用户名: admin  密码: Admin123")
    print("  用户1  - 用户名: john   密码: User123")
    print("  用户2  - 用户名: jane   密码: User123")
    print("=" * 60)

